﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using WalkingTec.Mvvm.Core;
using HengTong.Model._Admin;
using HengTong.Model.Db;
using HengTong.Model.Db.Ai;
using HengTong.Model.Db.Article;
using HengTong.Model.Db.Hr;
using HengTong.Model.Db.Hr.Attendance;
using HengTong.Model.Db.Hr.Attendance.Rule;
using HengTong.Model.Db.Hr.Bill;
using HengTong.Model.Db.Other;
using HengTong.Model.Db.Other.Bill;
using HengTong.Model.Db.SupplyChain.Material;
using HengTong.Model.Db.SupplyChain.Material.Bill;
using HengTong.Model.Db.SupplyChain.Partner;
using HengTong.Model.Db.SupplyChain.Purchase;
using HengTong.Model.Db.SupplyChain.Warehouse;
using HengTong.Model.Db.System;
using TiaoTaoHelper.Wtm.Models;

namespace HengTong.DataAccess
{
    public class DataContext : FrameworkContext
    {
        //_Admin
        public DbSet<FrameworkUser> FrameworkUsers { get; set; }
        public DbSet<FrameworkUserRole> FrameworkUserRoles { get; set; }
        public DbSet<FrameworkUserGroup> FrameworkUserGroups { get; set; }
        public DbSet<SysGroup> SysGroup { get; set; } //组织架构（部门）
        public DbSet<SysJobPosition> SysJobPosition { get; set; } //岗位信息
        public DbSet<SysJobPositionRole> SysJobPositionRole { get; set; } //岗位角色关联
        public DbSet<SysUserJobPosition> SysUserJobPosition { get; set; } //用户岗位关联
        public DbSet<SysSiteConfig> SysSiteConfig { get; set; } //站点配置
        public DbSet<SysOrg> SysOrg { get; set; } //公司
        public DbSet<SysUserFavorite> SysUserFavorite { get; set; } //用户收藏菜单
        public DbSet<SysTemplate> SysTemplate { get; set; } // 系统模板
        public DbSet<SysSeal> SysSeal { get; set; } // 系统印章
        public DbSet<SysSsoApplication> SysSsoApplication { get; set; } // SSO应用配置表

        //微信
        public DbSet<SysWechatUser> SysWechatUser { get; set; } //微信用户
        public DbSet<SysSmsAuthLog> SysSmsAuthLog { get; set; } //短信记录

        //编码
        public DbSet<SysCodeRule> SysCodeRule { get; set; } //编码规则
        public DbSet<SysCodeHistory> SysCodeHistory { get; set; } //编码历史
        public DbSet<SysBillRoute> SysBillRoute { get; set; } // 单据路由
        
        //AI
        public DbSet<SysPrompt> SysPrompt { get; set; } // 系统提示词
        public DbSet<SysPromptGroup> SysPromptGroup { get; set; } // 系统提示词分组

        // 人员信息-Person
        public DbSet<SysPerson> SysPerson { get; set; } //员工档案
        public DbSet<SysPersonEducation> SysPersonEducation { get; set; } //学习经历
        public DbSet<SysPersonEducationFile> SysPersonEducationFile { get; set; } // 学历附件表（多文件）
        public DbSet<SysPersonFamily> SysPersonFamily { get; set; } //家庭成员
        public DbSet<SysPersonWork> SysPersonWork { get; set; } //工作经历
        public DbSet<SysPersonTrainBatche> SysPersonTrainBatche { get; set; } // 培训批次表
        public DbSet<SysPersonTrainExam> SysPersonTrainExam { get; set; } //培训考试表
        public DbSet<SysPersonMedicalBatche> SysPersonMedicalBatche { get; set; } // 体检批次表
        public DbSet<SysPersonMedical> SysPersonMedical { get; set; } //员工体检表
        public DbSet<SysPersonResume> SysPersonResume { get; set; } //员工履历表
        public DbSet<SysPersonContract> SysPersonContract { get; set; } //员工合同表
        public DbSet<SysPersonContractFile> SysPersonContractFile { get; set; } // 员工合同附件表（多文件）
        public DbSet<SysPersonProfessionalTitle> SysPersonProfessionalTitle { get; set; } // 员工职称表
        public DbSet<SysPersonProfessionalTitleType> SysPersonProfessionalTitleType { get; set; } // 员工职称类别表
        public DbSet<SysPersonSocialSecurityScheme> SysPersonSocialSecurityScheme { get; set; } // 员工社保方案
        public DbSet<SysPersonSocialSecurity> SysPersonSocialSecurity { get; set; } // 员工社保信息
        public DbSet<SysPersonRepairBill> SysPersonRepairBill { get; set; } //员工档案补录
        public DbSet<SysPersonUpdateBill> SysPersonUpdateBill { get; set; } //员工档案更新

        //招聘模块-Hr
        public DbSet<SysHrStaffNeedRequestBill> SysHrStaffNeedRequestBill { get; set; } //用人需求申请
        public DbSet<SysHrStaffNeedRequestBillEntry> SysHrStaffNeedRequestBillEntry { get; set; } //用人需求明细
        public DbSet<SysHrStaffPool> SysHrStaffPool { get; set; } //用人需求池
        public DbSet<SysHrRecruitPublishRequestBill> SysHrRecruitPublishRequestBill { get; set; } // 招聘发布申请
        public DbSet<SysHrInterviewRequestBill> SysHrInterviewRequestBill { get; set; } //应聘面试表
        public DbSet<SysHrInterviewPool> SysHrInterviewPool { get; set; } //录用候选池
        public DbSet<SysHrOnboardingRequestBill> SysHrOnboardingRequestBill { get; set; } //员工档案入职
        public DbSet<SysHrJobAssignmentRequestBill> SysHrJobAssignmentRequestBill { get; set; } //员工岗位分配表
        public DbSet<SysHrJobAssignmentRequestBillEntry> SysHrJobAssignmentRequestBillEntry { get; set; } //分岗明细
        public DbSet<SysHrProbationRequestBill> SysHrProbationRequestBill { get; set; } //转正申请表
        public DbSet<SysHrTransferRequestBill> SysHrTransferRequestBill { get; set; } //员工调岗调薪申请表
        public DbSet<SysHrRenewRequestBill> SysHrRenewRequestBill { get; set; } //员工续签申请表
        public DbSet<SysHrRenewContractFile> SysHrRenewContractFile { get; set; } // 员工续签附件表（多文件）
        public DbSet<SysHrResignRequestBill> SysHrResignRequestBill { get; set; } // 员工离职申请表
        public DbSet<SysHrDismissRequestBill> SysHrDismissRequestBill { get; set; } //员工开除申请表
        public DbSet<SysHrRetireRequestBill> SysHrRetireRequestBill { get; set; } //员工退休申请表

        //考勤
        public DbSet<SysAttendanceShift> SysAttendanceShift { get; set; } //考勤班次
        public DbSet<SysAttendanceSubsidyRule> SysAttendanceSubsidyRule { get; set; } //考勤补贴规则
        public DbSet<SysAttendanceRecord> SysAttendanceRecord { get; set; } //人员考勤班次
        public DbSet<SysAttendanceShiftGroup> SysAttendanceShiftGroup { get; set; } //考勤班组
        public DbSet<SysAttendanceShiftAndGroup> SysAttendanceShiftAndGroup { get; set; } //班次与班组关联
        public DbSet<SysAttendanceRawRecord> SysAttendanceRawRecord { get; set; } //打卡记录

        // 日常模块-Daily
        public DbSet<SysDailyOutFactoryRequestBill> SysDailyOutFactoryRequestBill { get; set; } // 出厂申请表
        public DbSet<SysDailyLeaveRequestBill> SysDailyLeaveRequestBill { get; set; } // 请假出差申请表
        public DbSet<SysDailyCompOffRequestBill> SysDailyCompOffRequestBill { get; set; } // 调休申请
        public DbSet<SysDailySubstitutionRequestBill> SysDailySubstitutionRequestBill { get; set; } // 替班申请
        public DbSet<SysDailyShiftSwapRequestBill> SysDailyShiftSwapRequestBill { get; set; } // 换班申请
        public DbSet<SysDailyOvertimeRequestBill> SysDailyOvertimeRequestBill { get; set; } // 加班申请

        //活动中心
        public DbSet<SysActivityList> SysActivityList { get; set; } // 活动列表
        public DbSet<SysActivityParticipation> SysActivityParticipation { get; set; } // 活动参与
        public DbSet<SysActivitImages> SysActivitImages { get; set; } // 活动图片组

        //访客中心
        public DbSet<SysVisitorReason> SysVisitorReason { get; set; } // 访客事由
        public DbSet<SysVisitorRecordRequestBill> SysVisitorRecordRequestBill { get; set; } // 访客申请记录
        public DbSet<SysVisitorInformation> SysVisitorInformation { get; set; } // 访客信息

        //文章模块
        public DbSet<SysArticle> SysArticle { get; set; } // 文章
        public DbSet<SysArticleAttachment> SysArticleAttachments { get; set; } // 文章附件
        public DbSet<SysArticleCategory> SysArticleCategory { get; set; } // 文章分类
        public DbSet<SysArticleTag> SysArticleTag { get; set; } // 文章标签
        public DbSet<SysArticleTagMapping> SysArticleTagMapping { get; set; } // 文章标签映射

        public DbSet<SysDataPrivilege> SysDataPrivilege { get; set; } // 数据权限x'x
        public DbSet<SysWorkflow> SysWorkflow { get; set; } // 工作流
        public DbSet<SysWorkflowHistory> SysWorkflowHistory { get; set; } // 工作流历史记录
        public DbSet<SysTodoCenter> SysTodoCenter { get; set; } // 待办中心
        public DbSet<SysNotification> SysNotification { get; set; } // 通知中心
        public DbSet<SysNotificationCategory> SysNotificationCategory { get; set; } // 通知分类

        #region 供应链

        //物料
        public DbSet<SysMeasureUnitGroup> SysMeasureUnitGroup { get; set; } // 计量单位组
        public DbSet<SysMeasureUnit> SysMeasureUnit { get; set; } // 计量单位
        public DbSet<SysRawMaterial> SysRawMaterial { get; set; } // 原材料
        public DbSet<SysMaterialGroup> SysMaterialGroup { get; set; } // 物料组
        public DbSet<SysMaterial> SysMaterial { get; set; } // 物料
        public DbSet<SysMaterialSku> SysMaterialSku { get; set; } // 物料SKU
        public DbSet<SysMaterialAttribute> SysMaterialAttribute { get; set; } // 物料属性
        public DbSet<SysMaterialAttributeValue> SysMaterialAttributeValue { get; set; } // 物料属性值
        public DbSet<SysMaterialSkuAttributes> SysMaterialSkuAttributes { get; set; } // 物料SKU属性关联

        //物料单据
        public DbSet<SysMaterialChangeRequestBill> SysMaterialChangeRequestBill { get; set; } // 物料变更申请单

        //仓库
        public DbSet<SysWarehouse> SysWarehouse { get; set; } // 仓库
        public DbSet<SysWarehouseArea> SysWarehouseArea { get; set; } // 库区
        public DbSet<SysWarehouseLocation> SysWarehouseLocation { get; set; } // 库位
        public DbSet<SysWarehouseStock> SysWarehouseStock { get; set; } // 仓库物料库存

        //合作伙伴
        public DbSet<SysPartner> SysPartner { get; set; } // 合作伙伴

        //采购
        public DbSet<SysPurchaseRequestBill> SysPurchaseRequestBill { get; set; } // 采购申请单
        public DbSet<SysPurchaseRequestBillEntry> SysPurchaseRequestBillEntry { get; set; } // 采购申请单明细
        
        //采购需求池
        public DbSet<SysPurchaseRequirementPool> SysPurchaseRequirementPool { get; set; } // 采购需求池
        public DbSet<SysPurchaseRequirementPoolEntry> SysPurchaseRequirementPoolEntry { get; set; } // 采购需求池明细

        #endregion


        //任务
        public DbSet<SysTaskV2> SysTaskV2 { get; set; } // 任务V2


        public DataContext(CS cs)
            : base(cs)
        {
        }

        public DataContext(string cs, DBTypeEnum dbType) : base(cs, dbType)
        {
        }

        public DataContext(string cs, DBTypeEnum dbType, string version = null) : base(cs, dbType, version)
        {
        }

        public DataContext(DbContextOptions<DataContext> options) : base(options)
        {
        }

        // 启用 SQL 日志输出到控制台
        /*protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);

            // 启用 SQL 日志输出到控制台
            optionsBuilder
                .EnableSensitiveDataLogging() // 显示参数值
                .EnableDetailedErrors() // 显示详细错误
                .LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
        }*/


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // 为UnionId添加可空唯一索引
            modelBuilder.Entity<SysWechatUser>()
                .HasIndex(u => u.UnionId)
                .IsUnique()
                .HasFilter("UnionId IS NOT NULL");

            // 确保 SysGroup 映射到同一张表
            modelBuilder.Entity<FrameworkGroup>()
                .ToTable("FrameworkGroups")
                .HasDiscriminator<string>("Discriminator")
                .HasValue<FrameworkGroup>("FrameworkGroup")
                .HasValue<SysGroup>("SysGroup");

            modelBuilder.Entity<SysUserJobPosition>()
                .HasIndex(e => new { e.UserId, e.JobPositionId })
                .HasDatabaseName("IX_SysUserJobPosition_UserId_JobPositionId")
                .IsUnique();

            modelBuilder.Entity<SysJobPositionRole>()
                .HasIndex(e => new { e.JobPositionId, e.RoleId })
                .HasDatabaseName("IX_SysJobPositionRole_JobPositionId_RoleId")
                .IsUnique();

            // 设置 SysPerson 工号唯一索引 和 手机号 可空 唯一索引（包含 Discriminator）
            modelBuilder.Entity<SysPerson>()
                .HasIndex("StaffNo", "Discriminator")
                .IsUnique()
                .HasFilter("Discriminator = 'SysPerson'")
                .HasDatabaseName("IX_SysPerson_StaffNo_Discriminator");

            modelBuilder.Entity<SysPerson>()
                .HasIndex("Phone", "Discriminator")
                .IsUnique()
                .HasFilter("Phone IS NOT NULL AND Discriminator = 'SysPerson'")
                .HasDatabaseName("IX_SysPerson_Phone_Discriminator");

            // 为 SysHrInterviewRequestBill 的 StaffNo 添加可空唯一索引
            modelBuilder.Entity<SysHrInterviewRequestBill>()
                .HasIndex("StaffNo", "Discriminator")
                .IsUnique()
                .HasFilter("Discriminator = 'SysHrInterviewRequestBill'")
                .HasDatabaseName("IX_SysHrInterviewRequestBill_StaffNo_Discriminator");

            // 设置 FrameworkUser 手机号 可空 唯一索引
            modelBuilder.Entity<FrameworkUser>()
                .HasIndex(u => u.CellPhone)
                .IsUnique()
                .HasFilter("CellPhone IS NOT NULL");

            modelBuilder.Entity<SysBillRoute>()
                .HasIndex(e => e.CodeType)
                .IsUnique();

            modelBuilder.Entity<SysTodoCenter>()
                .HasIndex(e => e.ActivityId)
                .HasDatabaseName("IX_SysTodoCenter_ActivityId");

            modelBuilder.Entity<SysTodoCenter>()
                .HasIndex(e => e.CreateBy)
                .HasDatabaseName("IX_SysTodoCenter_CreateBy");

            modelBuilder.Entity<SysTodoCenter>()
                .HasIndex(e => new
                {
                    e.CreateBy,
                    e.CreateTime
                })
                .HasDatabaseName("IX_SysTodoCenter_CreateBy_CreateTime");

            modelBuilder.Entity<SysTodoCenter>()
                .HasIndex(e => new
                {
                    e.WorkflowId,
                    e.CreateBy
                })
                .HasDatabaseName("IX_SysTodoCenter_WorkflowId_CreateBy");

            // 配置 SysHrRenewRequestBill 和 SysPersonContract 的一对一关系
            modelBuilder.Entity<SysHrRenewRequestBill>()
                .HasOne(r => r.PersonContract)
                .WithOne(c => c.RequestBill)
                .HasForeignKey<SysHrRenewRequestBill>(r => r.PersonContractId)
                .OnDelete(DeleteBehavior.SetNull);

            // 配置 SysHrRenewRequestBill 和 SysPerson 的多对一关系
            modelBuilder.Entity<SysHrRenewRequestBill>()
                .HasOne(r => r.Person)
                .WithMany()
                .HasForeignKey(r => r.PersonId)
                .OnDelete(DeleteBehavior.SetNull);

            // 为 SysHrStaffPool 的 StaffNeedEntryId 添加可空唯一索引
            modelBuilder.Entity<SysHrStaffPool>()
                .HasIndex(e => e.StaffNeedEntryId)
                .IsUnique()
                .HasFilter("StaffNeedEntryId IS NOT NULL")
                .HasDatabaseName("IX_SysHrStaffPool_StaffNeedEntryId");

            // 为单据编号添加可空唯一索引
            modelBuilder.Entity<SysHrStaffPool>()
                .HasIndex(e => e.BillNo)
                .IsUnique()
                .HasFilter("BillNo IS NOT NULL")
                .HasDatabaseName("IX_SysHrStaffPool_BillNo");

            modelBuilder.Entity<SysHrInterviewPool>()
                .HasIndex(e => e.BillNo)
                .IsUnique()
                .HasFilter("BillNo IS NOT NULL")
                .HasDatabaseName("IX_SysHrInterviewPool_BillNo");

            modelBuilder.Entity<SysHrInterviewPool>()
                .HasIndex(e => e.HiredStaffNo)
                .IsUnique()
                .HasFilter("HiredStaffNo IS NOT NULL")
                .HasDatabaseName("IX_SysHrInterviewPool_HiredStaffNo");

            // 替班：双外键指向 SysPerson，禁用级联删除
            modelBuilder.Entity<SysDailySubstitutionRequestBill>(b =>
            {
                b.HasOne(x => x.Person)
                    .WithMany()
                    .HasForeignKey(x => x.PersonId)
                    .OnDelete(DeleteBehavior.Restrict); // 或 DeleteBehavior.NoAction

                b.HasOne(x => x.SubstitutePerson)
                    .WithMany()
                    .HasForeignKey(x => x.SubstitutePersonId)
                    .OnDelete(DeleteBehavior.Restrict); // 或 DeleteBehavior.NoAction
            });

            // 换班：同样禁用级联删除，防止未来扩展产生冲突
            modelBuilder.Entity<SysDailyShiftSwapRequestBill>(b =>
            {
                b.HasOne(x => x.Person)
                    .WithMany()
                    .HasForeignKey(x => x.PersonId)
                    .OnDelete(DeleteBehavior.Restrict); // 或 DeleteBehavior.NoAction

                b.HasOne(x => x.SwapPerson)
                    .WithMany()
                    .HasForeignKey(x => x.SwapPersonId)
                    .OnDelete(DeleteBehavior.Restrict); // 或 DeleteBehavior.NoAction
            });
            // 配置 SysDailyCompOffRequestBill 和 SysDailyOvertimeRequestBill 的多对多关系
            modelBuilder.Entity<SysCompOffOvertimeLink>()
                .HasOne(x => x.OvertimeRequestBill)
                .WithMany()
                .HasForeignKey(x => x.OvertimeRequestBillId)
                .OnDelete(DeleteBehavior.NoAction); // 禁用级联删除


            // 为 SysPersonRepairBill 设置非唯一索引
            /*modelBuilder.Entity<SysPersonRepairBill>()
                .HasIndex("StaffNo", "Discriminator")
                .IsUnique(false)
                .HasDatabaseName("IX_SysPersonRepairBill_StaffNo_Discriminator");

            modelBuilder.Entity<SysPersonRepairBill>()
                .HasIndex("Phone", "Discriminator")
                .IsUnique(false)
                .HasFilter("Phone IS NOT NULL")
                .HasDatabaseName("IX_SysPersonRepairBill_Phone_Discriminator");

            // 为 SysPersonUpdateBill 设置非唯一索引
            modelBuilder.Entity<SysPersonUpdateBill>()
                .HasIndex("StaffNo", "Discriminator")
                .IsUnique(false)
                .HasDatabaseName("IX_SysPersonRepairBill_StaffNo_Discriminator");

            modelBuilder.Entity<SysPersonUpdateBill>()
                .HasIndex("Phone", "Discriminator")
                .IsUnique(false)
                .HasFilter("Phone IS NOT NULL")
                .HasDatabaseName("IX_SysPersonRepairBill_Phone_Discriminator");*/
        }
    }

    /// <summary>
    /// DesignTimeFactory for EF Migration, use your full connection string,
    /// EF will find this class and use the connection defined here to run Add-Migration and Update-Database
    /// </summary>
    public class DataContextFactory : IDesignTimeDbContextFactory<DataContext>
    {
        public DataContext CreateDbContext(string[] args)
        {
#if DEBUG
            return new DataContext(
                "Server=42.225.116.55,19926;Database=HengTongTest;user id=sa;password=Jia123wei!;TrustServerCertificate=True;Pooling=true;Max Pool Size=100;Min Pool Size=5;",
                DBTypeEnum.SqlServer);
#else
            return new DataContext(
                "Server=127.0.0.1,14331;Database=HengTong;user id=HengTong;password=HengTong123654!;TrustServerCertificate=True;Pooling=true;Max Pool Size=100;Min Pool Size=5;",
                DBTypeEnum.SqlServer);
#endif
        }
    }
}